package org.xxpay.pay.channel.youkafu;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.google.common.collect.Maps;
import org.springframework.stereotype.Service;
import org.xxpay.common.http.HttpRequestTemplate;
import org.xxpay.common.util.sign.SignUtils;
import org.xxpay.common.util.str.StringUtils;
import org.xxpay.core.common.constant.PayConstant;
import org.xxpay.core.common.util.AmountUtil;
import org.xxpay.core.entity.PayOrder;
import org.xxpay.pay.channel.BasePayment;
import org.xxpay.pay.channel.maicheng.MaichengConfig;

import java.util.*;

@Service
public class YoukafuPaymentService extends BasePayment {
    private final static String logPrefix = "【优卡付】";
    @Override
    public String getChannelName() { return YoukafuPayConfig.CHANNEL_NAME; }
    @Override
    public JSONObject pay(PayOrder payOrder) {
        String channelId = payOrder.getChannelId();
        JSONObject retObj;
        switch (channelId) {
            case YoukafuPayConfig.CHANMEL_NAME_ALI_QR:
                retObj = doOrderReq(payOrder);
                break;
            default:
                retObj = buildRetObj(PayConstant.RETURN_VALUE_FAIL, "不支持的渠道[channelId="+channelId+"]");
                break;
        }
        return retObj;
    }

    /**
     * 查询订单
     * @param payOrder
     * @return
     */
    @Override
    public JSONObject query(PayOrder payOrder) {
        JSONObject retObj = buildRetObj();
        retObj.put(PayConstant.RETURN_PARAM_RETCODE, PayConstant.RETURN_VALUE_FAIL);
        retObj.put(PayConstant.RESULT_PARAM_ERRDES, "没有订单查询接口");
        return retObj;
    }
    //下单请求实现
    private JSONObject doOrderReq(PayOrder payOrder){
        YoukafuPayConfig config = new YoukafuPayConfig(getPayParam(payOrder));
        Map<String,Object> params = Maps.newHashMap();
        //设置请求参数
        setParames(payOrder, config, params);
        _log.info("{}请求数据:{}", getChannelName(), JSON.toJSONString(params));
        //将订单改为支付中
        rpcCommonService.rpcPayOrderService.updateStatus4Ing(payOrder.getPayOrderId(), null);
        HttpRequestTemplate requestTemplate = new HttpRequestTemplate(null);
        JSONObject origin = requestTemplate.postForObject(config.getRequestUrl()+YoukafuPayConfig.REQ_PAY_URL_FIXX, params, JSONObject.class);
        _log.info("{}响应数据:{}", getChannelName(), JSON.toJSONString(origin));
        // 响应对象
        JSONObject retObj = new JSONObject();
        if(StringUtils.equals("0",origin.getString("code"))){
            JSONObject data = JSONObject.parseObject(origin.getString("data"));
            return buildPayResultOfForm(retObj, payOrder,"<script type=\"text/javascript\">\n" +
                    "　　window.location.href=\""+ data.getString("qrcode")+"\";\n" +
                    "　　</script>" );
        }
        retObj.put(PayConstant.RETURN_PARAM_RETCODE, PayConstant.RETURN_VALUE_FAIL);
        retObj.put(PayConstant.RESULT_PARAM_ERRDES, origin.toJSONString());
        return retObj;
    }
    //设置请求参数
    private void setParames(PayOrder payOrder,YoukafuPayConfig config,  Map<String,Object> parameters){
        parameters.put("merchantid", config.getAppId());
        parameters.put("orderid", payOrder.getPayOrderId());
        parameters.put("amount", AmountUtil.convertCent2Dollar(String.valueOf(payOrder.getAmount())));
        parameters.put("paytype", config.getPayMode());
        parameters.put("client_ip", payOrder.getClientIp());
        parameters.put("notify_url", payConfig.getNotifyUrl(getChannelName()));
        parameters.put("sign", getSign(parameters, config.getPrivateKey()));
    }

    //获取sign
    private String getSign(Map<String,Object> params,String key){
        String signTxt = parameterText(params,"","sign");
        String sign = SignUtils.MD5.createSign(  signTxt, key  , SignUtils.CHARSET_UTF8);
        _log.info("{}待签名字符串：{}", logPrefix, signTxt+key);
        _log.info("{}签名结果：{}", logPrefix, sign);
        return sign;
    }
    //特定签名排序方式
    private static String parameterText(Map parameters, String separator, String... ignoreKey ) {
        if(parameters == null) {
            return "";
        }
        StringBuffer sb = new StringBuffer();
        if (null != ignoreKey){
            Arrays.sort(ignoreKey);
        }
        // TODO 2016/11/11 10:14 author: egan 已经排序好处理
        if (parameters instanceof SortedMap) {
            for (Map.Entry<String, Object> entry : (Set<Map.Entry<String, Object>>)parameters.entrySet()) {
                Object v = entry.getValue();
                if (null == v || "".equals(v.toString().trim()) || (null != ignoreKey && Arrays.binarySearch(ignoreKey, entry.getKey() ) >= 0)) {
                    continue;
                }
                sb.append(entry.getKey() ).append( v.toString().trim()).append(separator);
            }
//            if (sb.length() > 0 && !"".equals(separator)) {
//                sb.deleteCharAt(sb.length() - 1);
//            }
            return sb.toString();

        }


        // TODO 2016/11/11 10:14 author: egan 未排序须处理
        List<String> keys = new ArrayList<String>(parameters.keySet());
        //排序
        Collections.sort(keys);
        for (String k : keys) {
            String valueStr = "";
            Object o = parameters.get(k);
            if (null == o) {
                continue;
            }
            if (o instanceof String[]) {
                String[] values = (String[]) o;

                for (int i = 0; i < values.length; i++) {
                    String value = values[i].trim();
                    if ("".equals(value)){ continue;}
                    valueStr += (i == values.length - 1) ?  value :  value + ",";
                }
            } else if (o != null) {
                valueStr = o.toString();
            }
            if (null == valueStr || "".equals(valueStr.toString().trim()) || (null != ignoreKey && Arrays.binarySearch(ignoreKey, k ) >= 0)) {
                continue;
            }
            sb.append(k ).append( valueStr).append(separator);
        }
//        if (sb.length() > 0) {
//            sb.deleteCharAt(sb.length() - 1);
//        }
        return sb.toString();
    }
}
